#include "swpcompositiongraphicitem.h"

#include "../../documents/data/graphicdata.h"
#include "../../undo/basicitemcommands.h"
#include "../../utils/undomanager.h"
#include "../../utils/validatormanager.h"
#include "graphicitemcommon.h"

#include <lineeditdelegate.h>
#include <pathgraphicitem.h>

#include <QtGui/QGraphicsScene>

using namespace core;
using namespace gui;
using namespace swp;

typedef QPair<Property, AbstractLineGraphicItem::LabelAnchor> _Property;

SwpCompositionGraphicItem::SwpCompositionGraphicItem(
    QGraphicsItem* parent) : AbstractLineGraphicItem(
        QPointF(),
        QPointF(),
        QList<QPointF>(),
        parent),
        m_firstMul(),
        m_secondMul(),
        m_propertyOrder(),
        m_properties(),
        m_multiplicityDelegate(0)
{
    init();
}

SwpCompositionGraphicItem::SwpCompositionGraphicItem(
    const QPointF& startPoint,
    const QPointF& endPoint,
    const QList<QPointF>& anchors,
    QGraphicsItem* parent) : AbstractLineGraphicItem(
        startPoint,
        endPoint,
        anchors,
        parent),
        m_firstMul(),
        m_secondMul(),
        m_propertyOrder(),
        m_properties(),
        m_multiplicityDelegate(0)
{
    init();
}

SwpCompositionGraphicItem::~SwpCompositionGraphicItem()
{
    delete m_multiplicityDelegate;
}

int SwpCompositionGraphicItem::type() const
{
    return SWP_COMPOSITION_ITEM;
}

QString SwpCompositionGraphicItem::name() const
{
    return QObject::tr("Composition");
}

IEditorItem* SwpCompositionGraphicItem::copy() const
{
    return new SwpCompositionGraphicItem();
}

QList<Property> SwpCompositionGraphicItem::properties() const
{
    QList<Property> ret;

    foreach (const QString& name,
        m_propertyOrder)
    {
        ret.append(m_properties[name].first);
    }

    return ret;
}

QVariant SwpCompositionGraphicItem::propertyValue(
    const QString& propertyName) const
{
    QVariant ret;

    if (m_properties.contains(propertyName))
    {
        const _Property prop = m_properties[propertyName];
        ret = prop.first.value();
    }

    return ret;
}

void SwpCompositionGraphicItem::propertyChanged(const QString& property,
    const QVariant& newValue, bool silent)
{
    if (m_properties.contains(property) &&
        propertyValue(property) != newValue)
    {
        _Property prop = m_properties[property];

        if (!silent)
        {
            PropertyChangeCommand* command = new PropertyChangeCommand(
                this, prop.first, newValue);

            UndoManager::getInstance()->push(
                dynamic_cast<IDocumentData*>(scene()), command);
        }
        else
        {
            prop.first.setValue(newValue);
            setLabel(prop.second, newValue.toString());

            m_properties[property] = prop;
        }

        if (silent && isSelected()) {
            setSelected(false);
            setSelected(true);
        }

        if (silent)
        {
            GraphicData* data = dynamic_cast<GraphicData*>(m_documentData);

            Q_ASSERT(data != 0); // shouldn't be null

            data->emitDataChanged();
        }
    }
}

QVariantList SwpCompositionGraphicItem::optionList(
    const QString& propertyName) const
{
    QVariantList ret;

    return ret;
}

QVariantList SwpCompositionGraphicItem::autocomplete(
    const QString& propertyName) const
{
    QVariantList ret;

    return ret;
}

QPair<QPen, QBrush> SwpCompositionGraphicItem::endArrowPalette() const
{
    QPair<QPen, QBrush> ret;

    QPen pen(QColor(Qt::black));
    pen.setWidth(2);
    QBrush brush(QColor(Qt::black));

    ret.first = pen;
    ret.second = brush;

    return ret;
}

void SwpCompositionGraphicItem::createArrows()
{
    QPolygonF endArrow;
    endArrow << QPointF(-10, 0) << QPointF(0, -8) << QPointF(10, 0) <<
        QPointF(0, 8) << QPointF(-10, 0);

    QPainterPath _endArrow;
    _endArrow.addPolygon(endArrow);
    //_endArrow.closeSubpath();

    setEndArrow(new gui::PathGraphicItem(_endArrow));
}

void SwpCompositionGraphicItem::init()
{
    m_multiplicityDelegate = new LineEditDelegate();
    m_multiplicityDelegate->setValidator(
        ValidatorManager::getInstance()->getValidator(
            "MultiplicityValidator"));

    m_firstMul.Name = "firstMul";
    m_firstMul.Text = QObject::tr("First multiplicity");
    m_firstMul.setValue("");
    m_firstMul.setDelegate(m_multiplicityDelegate);

    m_properties[m_firstMul.Name] = QPair<Property, LabelAnchor>(
        m_firstMul, AbstractLineGraphicItem::StartAbove);

    m_secondMul.Name = "secondMul";
    m_secondMul.Text = QObject::tr("Second multiplicity");
    m_secondMul.setValue("");
    m_secondMul.setDelegate(m_multiplicityDelegate);

    m_properties[m_secondMul.Name] = QPair<Property, LabelAnchor>(
        m_secondMul, AbstractLineGraphicItem::EndAbove);

    m_propertyOrder.append(m_firstMul.Name);
    m_propertyOrder.append(m_secondMul.Name);

    setFlags(flags() | QGraphicsItem::ItemIsSelectable);

    createArrows();

    updateLine();
}
